// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) definits fieldsfirst ansi space safe 
// Source File Name:   SimpleRobot.java

package jones;

import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import javax.swing.SwingUtilities;
import jones.behavior.Arbiter;
import jones.behavior.Behavior;
import jones.behavior.BehaviorFactory;
import jones.behavior.BehaviorFactoryException;
import jones.behavior.Cruise;
import jones.behavior.Escape;
import jones.behavior.PriorityListArbiter;
import jones.behavior.Programmable;
import jones.behavior.SimplePriorityListArbiter;
import jones.gui.RemoteControl;
import jones.rigid.ConvexPolygon;
import jones.rigid.RegularPolygon;
import jones.rigid.RigidBody;
import jones.rigid.SimpleRigidBody;
import jones.rigid.WedgePolygon;

// Referenced classes of package jones:
//            PhotoSensor, SimObject, SimpleRobotInterface, ValueNotAvailableException, 
//            World, RemoteControlState

public class SimpleRobot extends SimpleRigidBody
    implements RigidBody, SimObject, SimpleRobotInterface, Programmable
{

    private static final int MAX_WHEEL_SPEED = 255;
    private static final ConvexPolygon ROBOT_SHAPE;
    private static final Point2D CENTER_OF_MASS = new Point();
    private static final double WHEEL_BASE_LENGTH = 40D;
    private static final Point2D LEFT_WHEEL = new java.awt.geom.Point2D.Double(0.0D, -20D);
    private static final Point2D RIGHT_WHEEL = new java.awt.geom.Point2D.Double(0.0D, 20D);
    private static final double MIN_ANGLE = 0.050000000000000003D;
    private static final int FRAMES_PER_SEC = 25;
    private static final double MAX_SPEED = 111.26473981463852D;
    private static final double MAX_ROTATION = 5.5632369907319257D;
    private static final double NOISE = 20D;
    private static final double ROBOT_FRONT = 0D;
    private static final double PHOTO_ANGLE = 0.78539816339744828D;
    private static final double PHOTO_ORIENTATION = 0.78539816339744828D;
    private static final double PHOTO_X;
    private static final double PHOTO_Y;
    private static final double IR_SWEEP_ANGLE = 0.78539816339744828D;
    private static final double IR_SWEEP_ORIENTATION = 0.78539816339744828D;
    private static final double IR_SWEEP_RADIUS;
    private static final int IR_SWEEP_SIDES = 3;
    private static final ConvexPolygon LEFT_IR_SWEEP;
    private static final ConvexPolygon RIGHT_IR_SWEEP;
    private PhotoSensor leftPhotoSensor = null;
    private PhotoSensor rightPhotoSensor = null;
    private Point2D wheel = null;
    private ConvexPolygon iRSweep = null;
    private AffineTransform transform = null;
    private int leftWheelSpeed = 0;
    private int rightWheelSpeed = 0;
    private boolean isBumping = false;
    private boolean isPushing = false;
    private boolean isLeftIROn = false;
    private boolean isRightIROn = false;
    private Behavior behaviors[] = {
        new Escape(), new Cruise()
    };
    private PriorityListArbiter arbiter = null;
    private World world = null;
    private RemoteControl remoteControl = null;

    public SimpleRobot(SimpleRobot robot, World world)
    {
        super(((SimpleRigidBody) (robot)));
        wheel = ((Point2D) (new java.awt.geom.Point2D.Double()));
        iRSweep = new ConvexPolygon();
        transform = new AffineTransform();
        leftWheelSpeed = 0;
        rightWheelSpeed = 0;
        isBumping = false;
        isPushing = false;
        isLeftIROn = false;
        isRightIROn = false;
        arbiter = ((PriorityListArbiter) (new SimplePriorityListArbiter(((SimpleRobotInterface) (this)), behaviors)));
        remoteControl = new RemoteControl();
        this.world = world;
        behaviors = new Behavior[robot.behaviors.length];
        for (int i = 0; i < behaviors.length; i++)
            try
            {
                behaviors[i] = BehaviorFactory.copy(robot.behaviors[i]);
            }
            catch (BehaviorFactoryException ex)
            {
                ex.printStackTrace();
            }

        arbiter = ((PriorityListArbiter) (new SimplePriorityListArbiter(((SimpleRobotInterface) (this)), behaviors)));
        init();
    }

    public SimpleRobot(double x, double y, double orientation, World world)
    {
        super(ROBOT_SHAPE, CENTER_OF_MASS.getX(), CENTER_OF_MASS.getY(), 0.0D);
        wheel = ((Point2D) (new java.awt.geom.Point2D.Double()));
        iRSweep = new ConvexPolygon();
        transform = new AffineTransform();
        leftWheelSpeed = 0;
        rightWheelSpeed = 0;
        isBumping = false;
        isPushing = false;
        isLeftIROn = false;
        isRightIROn = false;
        arbiter = ((PriorityListArbiter) (new SimplePriorityListArbiter(((SimpleRobotInterface) (this)), behaviors)));
        remoteControl = new RemoteControl();
        this.world = world;
        setLocation(x, y);
        setOrientation(orientation);
        setPushable(false);
        init();
    }

    private void init()
    {
        leftPhotoSensor = new PhotoSensor(PHOTO_X, -PHOTO_Y, -0.78539816339744828D, world);
        rightPhotoSensor = new PhotoSensor(PHOTO_X, PHOTO_Y, 0.78539816339744828D, world);
        attach(((jones.rigid.Attachable) (leftPhotoSensor)));
        attach(((jones.rigid.Attachable) (rightPhotoSensor)));
    }

    public Behavior[] getBehaviors()
    {
        return behaviors;
    }

    public void setBehaviors(Behavior behaviors[])
    {
        this.behaviors = behaviors;
        setChanged();
    }

    public Arbiter getArbiter()
    {
        return ((Arbiter) (arbiter));
    }

    public void setArbiter(Arbiter arbiter)
    {
        this.arbiter = (PriorityListArbiter)arbiter;
        setChanged();
    }

    public void update(double time)
    {
        setBumping(world.isColliding(((RigidBody) (this))));
        setPushing(world.isPushing(((RigidBody) (this))));
        setLeftIROn(world.intersects(getLeftIRSweep(iRSweep)));
        setRightIROn(world.intersects(getRightIRSweep(iRSweep)));
        leftPhotoSensor.update(time);
        rightPhotoSensor.update(time);
        for (int i = 0; i < behaviors.length; i++)
        {
            behaviors[i].update(time);
            behaviors[i].act(((Arbiter) (arbiter)));
        }

        arbiter.choose();
        setChanged();
    }

    public ConvexPolygon getLeftIRSweep(ConvexPolygon p)
    {
        if (p == null)
            p = new ConvexPolygon();
        p.setPolygon(((jones.rigid.Polygon) (LEFT_IR_SWEEP)));
        p.transform(getTransform(transform));
        return p;
    }

    public ConvexPolygon getRightIRSweep(ConvexPolygon p)
    {
        if (p == null)
            p = new ConvexPolygon();
        p.setPolygon(((jones.rigid.Polygon) (RIGHT_IR_SWEEP)));
        p.transform(getTransform(transform));
        return p;
    }

    public double getLeftWheelX()
    {
        getTransform(transform).transform(LEFT_WHEEL, wheel);
        return wheel.getX();
    }

    public double getLeftWheelY()
    {
        getTransform(transform).transform(LEFT_WHEEL, wheel);
        return wheel.getY();
    }

    public double getRightWheelX()
    {
        getTransform(transform).transform(RIGHT_WHEEL, wheel);
        return wheel.getX();
    }

    public double getRightWheelY()
    {
        getTransform(transform).transform(RIGHT_WHEEL, wheel);
        return wheel.getY();
    }

    public int getMaxWheelSpeed()
    {
        return 255;
    }

    public double getWheelBaseLength()
    {
        return 40D;
    }

    public synchronized int getLeftWheelSpeed()
    {
        return (int)(((double)leftWheelSpeed * 111.26473981463852D) / 255D);
    }

    public synchronized void setLeftWheelSpeed(int leftWheelSpeed)
    {
        if (leftWheelSpeed > 255)
            this.leftWheelSpeed = 255;
        else
        if (leftWheelSpeed < -255)
            this.leftWheelSpeed = -255;
        else
            this.leftWheelSpeed = leftWheelSpeed;
        setWheelSpeeds();
        setChanged();
    }

    public synchronized int getRightWheelSpeed()
    {
        return (int)(((double)rightWheelSpeed * 111.26473981463852D) / 255D);
    }

    public synchronized void setRightWheelSpeed(int rightWheelSpeed)
    {
        if (rightWheelSpeed > 255)
            this.rightWheelSpeed = 255;
        else
        if (rightWheelSpeed < -255)
            this.rightWheelSpeed = -255;
        else
            this.rightWheelSpeed = rightWheelSpeed;
        setWheelSpeeds();
        setChanged();
    }

    private void setWheelSpeeds()
    {
        double leftWheelSpeed = ((double)this.leftWheelSpeed * 111.26473981463852D) / 255D;
        double rightWheelSpeed = ((double)this.rightWheelSpeed * 111.26473981463852D) / 255D;
        if (!world.isFantasyMode())
        {
            leftWheelSpeed += (Math.random() - 0.5D) * 20D;
            rightWheelSpeed += (Math.random() - 0.5D) * 20D;
        }
        if (leftWheelSpeed == rightWheelSpeed)
        {
            double orientation = getOrientation();
            setVelocity(leftWheelSpeed, 0.0D);
            setRelativeVelocity(true);
            setAngularVelocity(0.0D);
        } else
        if (leftWheelSpeed > rightWheelSpeed)
        {
            double innerRadius = (rightWheelSpeed * 40D) / (leftWheelSpeed - rightWheelSpeed);
            double x = RIGHT_WHEEL.getX() + (innerRadius * (RIGHT_WHEEL.getX() - LEFT_WHEEL.getX())) / 40D;
            double y = RIGHT_WHEEL.getY() + (innerRadius * (RIGHT_WHEEL.getY() - LEFT_WHEEL.getY())) / 40D;
            setAxis(x, y);
            setAngularVelocity((leftWheelSpeed - rightWheelSpeed) / 40D);
            setVelocity(0.0D, 0.0D);
        } else
        {
            double innerRadius = (leftWheelSpeed * 40D) / (rightWheelSpeed - leftWheelSpeed);
            double x = LEFT_WHEEL.getX() + (innerRadius * (LEFT_WHEEL.getX() - RIGHT_WHEEL.getX())) / 40D;
            double y = LEFT_WHEEL.getY() + (innerRadius * (LEFT_WHEEL.getY() - RIGHT_WHEEL.getY())) / 40D;
            setAxis(x, y);
            setAngularVelocity((leftWheelSpeed - rightWheelSpeed) / 40D);
            setVelocity(0.0D, 0.0D);
        }
    }

    public void setRotation(double rotation)
    {
        if (rotation > 5.5632369907319257D)
            setAngularVelocity(5.5632369907319257D);
        else
        if (rotation < -5.5632369907319257D)
            setAngularVelocity(-5.5632369907319257D);
        else
            setAngularVelocity(rotation);
        setAxis(0.0D, 0.0D);
    }

    public void setTranslation(double translation)
    {
        if (translation > 111.26473981463852D)
            setVelocity(111.26473981463852D, 0.0D);
        else
        if (translation < -111.26473981463852D)
            setVelocity(-111.26473981463852D, 0.0D);
        else
            setVelocity(translation, 0.0D);
        setRelativeVelocity(true);
        setChanged();
    }

    private synchronized void setBumping(boolean isBumping)
    {
        this.isBumping = isBumping;
    }

    public synchronized boolean isBumping()
    {
        return isBumping;
    }

    private synchronized void setPushing(boolean isPushing)
    {
        this.isPushing = isPushing;
    }

    public synchronized boolean isPushing()
    {
        return isPushing;
    }

    public int getLeftPhoto()
        throws ValueNotAvailableException
    {
        return leftPhotoSensor.getValue();
    }

    public int getRightPhoto()
        throws ValueNotAvailableException
    {
        return rightPhotoSensor.getValue();
    }

    private synchronized void setLeftIROn(boolean isLeftIROn)
    {
        this.isLeftIROn = isLeftIROn;
    }

    public synchronized boolean isLeftIROn()
    {
        return isLeftIROn;
    }

    private synchronized void setRightIROn(boolean isRightIROn)
    {
        this.isRightIROn = isRightIROn;
    }

    public synchronized boolean isRightIROn()
    {
        return isRightIROn;
    }

    public Behavior getLastChosenBehavior()
    {
        return arbiter.getLastChosenBehavior();
    }

    public RemoteControlState getRemoteControlState()
    {
        SwingUtilities.invokeLater(new Runnable() {

            public void run()
            {
                if (!remoteControl.isVisible())
                    remoteControl.show();
            }

        }
);
        return remoteControl.getState();
    }

    static 
    {
        ROBOT_SHAPE = ((ConvexPolygon) (new RegularPolygon(50, 3D)));
        PHOTO_X = ROBOT_SHAPE.getMaxX() * Math.cos(0.78539816339744828D);
        PHOTO_Y = ROBOT_SHAPE.getMaxX() * Math.sin(0.78539816339744828D);
        IR_SWEEP_RADIUS = ROBOT_SHAPE.getMaxX();
        LEFT_IR_SWEEP = ((ConvexPolygon) (new WedgePolygon(ROBOT_SHAPE.getMaxX() * Math.cos(-0.78539816339744828D), ROBOT_SHAPE.getMaxX() * Math.sin(-0.78539816339744828D), -0.78539816339744828D, -0.78539816339744828D, IR_SWEEP_RADIUS, 3)));
        RIGHT_IR_SWEEP = ((ConvexPolygon) (new WedgePolygon(ROBOT_SHAPE.getMaxX() * Math.cos(0.78539816339744828D), ROBOT_SHAPE.getMaxX() * Math.sin(0.78539816339744828D), 0.78539816339744828D, 0.78539816339744828D, IR_SWEEP_RADIUS, 3)));
    }

}
